package cn.uncode.rpc.core;

import java.lang.reflect.Method;

import cn.uncode.rpc.common.log.Logger;
import cn.uncode.rpc.common.log.LoggerFactory;
import cn.uncode.rpc.exception.FrameworkException;
import cn.uncode.rpc.spi.SpiMeta;



@SpiMeta(name = "uncode")
public class DefaultInvoker<T> extends AbstractInvoker<T> {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(DefaultInvoker.class);
	
    protected T proxyImpl;

    public DefaultInvoker(T proxyImpl, URL url, Class<T> clz) {
        super(url, clz);
        this.proxyImpl = proxyImpl;
    }

	@Override
	protected Response doInvoke(Request request) {
		DefaultResponse response = new DefaultResponse();

		Method method = lookup(request);

		if (method == null) {
			FrameworkException exception = new FrameworkException(
					"Service method not exist: " + request.getInterfaceName() + "." + request.getMethodName() + "("
							+ request.getParamtersDesc() + ")");

			response.setException(exception);
			return response;
		}

		try {
			Object value = method.invoke(proxyImpl, request.getArguments());
			response.setValue(value);
		} catch (Exception e) {
			if (e.getCause() != null) {
				LOGGER.error("Exception caught when method invoke: " + e.getCause());
				response.setException(new FrameworkException("provider call process error", e.getCause()));
			} else {
				response.setException(new FrameworkException("provider call process error", e));
			}
		} catch (Throwable t) {
			// 如果服务发生Error，将Error转化为Exception，防止拖垮调用方
			if (t.getCause() != null) {
				response.setException(
						new FrameworkException("provider has encountered a fatal error!", t.getCause()));
			} else {
				response.setException(new FrameworkException("provider has encountered a fatal error!", t));
			}

		}
		// 传递rpc版本和attachment信息方便不同rpc版本的codec使用。
		response.setRpcProtocolVersion(request.getRpcProtocolVersion());
		response.setAttachments(request.getAttachments());
		return response;
	}

	@Override
	protected boolean doInit() {
		return true;
	}

}
